﻿using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Web; 
using System.Web.Mvc;
using System.Reflection;
using System.ComponentModel.DataAnnotations;
using System;
using SRF.Common;

namespace SRF.UI.Html
{
    /// <summary>
    /// 树形下来列表htmlHelper
    /// </summary>
    public static class TreeSelectorExtensions
    {
        #region

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TModel">实体类型</typeparam>
        /// <typeparam name="TProperty">属性值的类型</typeparam>
        /// <typeparam name="TItem">列表实体类型</typeparam>
        /// <param name="htmlHelper"></param>
        /// <param name="expression">获取实体属性值的表达式</param>
        /// <param name="treeData">树形里边</param>
        /// <param name="getId"></param>
        /// <param name="getPId"></param>
        /// <param name="getName"></param>
        /// <param name="excludeId"></param>
        /// <returns></returns>
        [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an appropriate nesting of generic types")]
        public static MvcHtmlString TreeSelectorFor<TModel, TProperty, TItem>(this HtmlHelper<TModel> htmlHelper,
            Expression<Func<TModel, TProperty>> expression,
            IList<TItem> treeData, Func<TItem, string> getId, Func<TItem, string> getPId,
            Func<TItem, string> getName, string excludeId = "")
        {
            ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);

            return MakeTreeSelectorHtml<TItem>(metadata.PropertyName, metadata.Model, treeData,
                getId, getPId, getName, excludeId,
                htmlHelper.GetUnobtrusiveValidationAttributes(metadata.PropertyName, metadata));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TModel">实体类型</typeparam>
        /// <typeparam name="TProperty">属性值的类型</typeparam>
        /// <typeparam name="TItem">列表实体类型</typeparam>
        /// <param name="htmlHelper"></param>
        /// <param name="expression">获取实体属性值的表达式</param>
        /// <param name="treeData">树形里边</param>
        /// <param name="getId"></param>
        /// <param name="getPId"></param>
        /// <param name="getName"></param>
        /// <param name="excludeId"></param>
        /// <returns></returns>
        [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an appropriate nesting of generic types")]
        public static MvcHtmlString TreeSelector<TItem>(this HtmlHelper htmlHelper,
            string name, object value,
            IList<TItem> treeData, Func<TItem, string> getId, Func<TItem, string> getPId,
            Func<TItem, string> getName, string excludeId = "")
        {
            return MakeTreeSelectorHtml<TItem>(name, value, treeData, getId, getPId, getName, excludeId);
        }

        private static MvcHtmlString MakeTreeSelectorHtml<TItem>(string name, object value, IList<TItem> treeData,
            Func<TItem, string> getId, Func<TItem, string> getPId,
            Func<TItem, string> getName, string excludeId,
            IDictionary<string, object> attributes = null)
        {
            StringBuilder htmlBuilder = new StringBuilder();

            htmlBuilder.Append("<div id='div-{1}'>{0}");
            htmlBuilder.Append("<a id='reset-{1}' class='tree-reset icon-remove'></a></div>");
            htmlBuilder.Append("<ul id='tree-{1}' class='tree-ul ztree'></ul>");
            htmlBuilder.Append("<input type='hidden' name='{1}' />");
            htmlBuilder.Append("<script type='text/javascript'>");
            htmlBuilder.Append("    loadTreeSelector('{1}', {2},'{3}');");
            htmlBuilder.Append("</script>");

            StringBuilder jsonDataBuilder = new StringBuilder("[");
            if (treeData != null)
            {
                if (!string.IsNullOrEmpty(excludeId))
                {
                    treeData.RemoveByTree(excludeId, getId, getPId);
                }
                foreach (TItem m in treeData)
                {
                    jsonDataBuilder.AppendFormat("{{id:'{0}',pId:'{1}',name:'{2}'}},", getId(m), getPId(m), getName(m));
                }
                if (treeData.Count > 0)
                {
                    jsonDataBuilder.Remove(jsonDataBuilder.Length - 1, 1);
                }
            }
            jsonDataBuilder.Append("]");

            TagBuilder tagBuilder = new TagBuilder("input");
            tagBuilder.MergeAttribute("id", "text-" + name);
            tagBuilder.MergeAttribute("type", "text");
            tagBuilder.MergeAttribute("readonly", "readonly");
            tagBuilder.AddCssClass("tree-textbox");
            if (attributes != null)
                tagBuilder.MergeAttributes(attributes, true);


            var html = string.Format(htmlBuilder.ToString(), tagBuilder.ToString(TagRenderMode.SelfClosing), name, jsonDataBuilder, value);

            return new MvcHtmlString(html);
        }
 
        #endregion
    }
}